package org.study.springboot.learning.design.strategy;

/**
 * <p>Title: TestMain <p>
 * <p>Description: 调用这个类的地方可以自行决定使用哪种策略：<p>
 *
 * @Author ZhangSY
 * @Date 2021/7/5 23:21
 * @Version v1.0
 **/
public class TestMain {
    /*
    策略模式的使用场景
    1、购物系统
举一个实际例子吧。假如有一个购物系统，在用户付款的时候，会产生很多场景，根据用户的不同情况算出不同用户要付款的金额，这时候最直观的一种做法是：
在付款的里面写N多的if...else if...else，判断用户的场景，根据场景计算用户付款金额。
这种设计明显违反了开闭原则。开闭原则的"闭"，指的是对修改关闭，但是这里假如算法又多了几种，那么必须再次修改这个付款的类。
这时候就可以使用策略模式。在付款的类里面持有一个付款接口的引用，每次根据不同场景传入一个具体的策略就好了。比如A类中要使用S0算法，就传入一个S0策略；B类中要使用S1算法，就传入一个S1算法。不需要把判断都放在付款的类中，代码的可读性、可维护性也更高了。付款这个类甚至可以直接生成一个.class文件放在一个jar包里面供调用。
2、使得代码更优雅、更易维护
假如你的代码中某处有一个打分系统，你为这个打分系统写了一段非常长的逻辑，某天，产品部门的同事找你，给我换一段打分逻辑，此时，有两种做法：
（1）把原有的打分逻辑删除，但这么做一个缺点是是看不到以前的打分算法了，另一个缺点是如果以后打分算法要换回来就找不到代码，虽然SVN和GIT这种版本管理工具都有历史提交记录的功能，但还是显得麻烦
（2）把原有的打分逻辑注释，但这么做的最大缺点是代码中有大量的注释，尤其在策略逻辑非常长的时候，这就导致了代码的可读性非常差
此时，就可以使用策略模式，将打分逻辑抽象为一种策略，换打分策略，新增一个策略的实现类，最后再让代码中传入新的策略实现类即可。
     */
    public static void main(String[] args) {
        Strategy strategyA  = new StrategyA();
        Strategy strategyB = new StrategyB();
        Context context = new Context(strategyA);
        context.setStrategyMethod();
        context = new Context(strategyB);
        context.setStrategyMethod();
    }
}
